package com.lollipop.synthential.list;

import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @Author: J.K
 * @Date: 2021-07-17 08:58
 * @Description: List的浅拷贝和深拷贝
 * list本质上是数组，而数组的是以地址的形式进行存储。
 * 浅拷贝：List A -> List B 将A的内容复制给了B，java中相同内容的数组指向同一地址，即进行浅拷贝后A与B指向同一地址。A和B一个改变另一个也会改变
 * 深拷贝：List A -> List B 将A复制给B的同时，给B创建新的地址，再将地址A的内容传递到地址B。ListA与ListB内容一致，但是由于所指向的地址不同，所以改变相互不受影响。
 */
public class ListCopy {
    public static void main(String[] args) {
        List<String> listA = new ArrayList<>();
        listA.add("lollipop");
        listA.add("marshmallow");
        shallowCopy1(listA);
        shallowCopy2(listA);
        shallowCopy3(listA);
        shallowCopy4(listA);
    }

    /**
     * 浅拷贝-1.遍历循环复制
     *
     * @param listA
     */
    private static void shallowCopy1(List<String> listA) {
        List<String> listB = new ArrayList<>(listA.size());
        for (String s : listA) {
            listB.add(s);
        }
        System.out.println("1.遍历循环复制-listA:" + listA);
        System.out.println("1.遍历循环复制-listB:" + listB);
    }

    /**
     * 浅拷贝：2.使用List实现类的构造方法
     *
     * @param listA
     */
    private static void shallowCopy2(List<String> listA) {
        List<String> listB = new ArrayList<>(listA);
        System.out.println("2.List实现类的构造方法-listA:" + listA);
        System.out.println("2.List实现类的构造方法-listB:" + listB);
    }

    /**
     * 浅拷贝：3.使用list.addAll()方法
     *
     * @param listA
     */
    private static void shallowCopy3(List<String> listA) {
        List<String> listB = new ArrayList<>();
        listB.addAll(listA);
        System.out.println("3.使用list.addAll()方法-listA:" + listA);
        System.out.println("3.使用list.addAll()方法-listB:" + listB);
    }

    /**
     * 浅拷贝：4.使用System.arraycopy()方法
     *
     * @param listA
     */
    private static void shallowCopy4(List<String> listA) {
        Object[] objects = listA.toArray();
        String[] strings = new String[objects.length];
        System.arraycopy(objects, 0, strings, 0, objects.length);
        List<String> listB = new ArrayList<>();
        Collections.addAll(listB, strings);
        System.out.println("4.使用System.arraycopy()方法-listA:" + listA);
        System.out.println("4.使用System.arraycopy()方法-listB:" + listB);
        // 修改listB
        listB.remove(0);
        System.out.println("4.使用System.arraycopy()方法-listA:" + listA);

    }

    /**
     * 深拷贝：1.使用序列化方法
     *
     * @param src
     * @param <T>
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static <T> List<T> deepCopy(List<T> src) throws IOException, ClassNotFoundException {
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(byteOut);
        out.writeObject(src);

        ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
        ObjectInputStream in = new ObjectInputStream(byteIn);
        @SuppressWarnings("unchecked")
        List<T> dest = (List<T>) in.readObject();
        return dest;
    }


}

